//--------------------------------------------------
/**
 *
 *      Hand Gesture Recognition System
 *
 */
//--------------------------------------------------
/**
 * //MODEL CLASS//
 * Clase Model que describe un Modelo Oculto de Marcov
 *
 * @author  Edwin Cobos & Cesar Murcia
 * @version HGR_v1.3
 *
 * Revisado: 18/11/11
 */
//--------------------------------------------------
//PACKAGE//
package hmm;
//IMPORT//
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Arrays;

//--------------------------------------------------
/** 
 * Clase Model que describe un Modelo Oculto de Marcov
 */
public class Model
{
    //--------------------------------------------------
     /**
     * Número de estados.
     */
    public int N;    

    /**
     * Número de observaciones
     */
    public String[] M;

    /**
     * Distribución de probabilidades de las transiciones entre estados
     */
    public float[][] A;

    /**
     * Distribución de probabilidades de las transiciones entre observaciones
     */
    public float[][] B;

    /**
     * Probabilidades iniciales
     */
    public float[] Pi;

    /**
     * Separador de la salida
     */
    public static final String SEPARATION_TOKEN = " ";
    
    //--------------------------------------------------
    /**
     * Constructor del modelo (lambda)
     * @param n Número de estado
     * @param m Número de Observaciones
     * @param a Distribución de probabilidades de las transiciones entre estados
     * @param b Distribución de probabilidades de las transiciones entre observaciones
     * @param pi Probabilidades iniciales
     */
    public Model(int n, String[] m, float[][] a, float[][] b, float[] pi)
    {
        this.N = n;
	this.Pi = pi;
	this.A = a;
	this.B = b;
        this.M = m;

        /*this.B = new float[b.length][];
        for(int i=0 ;i<this.B.length; i++)
        {
            this.B[i] = new float[b[i].length];
            for(int j=0; j<this.B[i].length; j++)
            {
                this.B[i][j] = new Float(b[i][j]);
            }
        }*/
	
    }

    /*public Object clone()
    {
        Model obj=null;
        try{
            obj=(Model)super.clone();
        }catch(CloneNotSupportedException ex){
            System.out.println(" no se puede duplicar");
        }
        obj.A = obj.A.clone();
        return obj;
    }*/
    //--------------------------------------------------
    //@Override
    /**
     * Salida a String de un modelo
     */
    public String toString()
    {
	StringBuilder returnValue;

	returnValue = new StringBuilder();
	returnValue.append(N).append("\n");	
        
        float zero =0;        
	
	for (String event : M)
        {
	    returnValue.append(event).append(Model.SEPARATION_TOKEN);
	}
	returnValue.deleteCharAt(returnValue.length() - 1);
        returnValue.append("\n#Pi\n");
        for (int i = 0; i < Pi.length; i++)
        {
	    returnValue.append(Pi[i]).append(Model.SEPARATION_TOKEN);
	}
	returnValue.deleteCharAt(returnValue.length() - 1);

	returnValue.append("\n#A\n");
	for (int i = 0; i < A.length; i++)
        {
	    if (i != 0)
            {
		returnValue.append("\n");
	    }
	    for (int j = 0; j < A[i].length; j++)
            {
		returnValue.append(A[i][j]).append(Model.SEPARATION_TOKEN);
	    }
	}
	returnValue.deleteCharAt(returnValue.length() - 1);

        //returnValue.append("\nB").append(Arrays.deepToString(B));
        returnValue.append("\n#B\n");
	for (int i = 0; i < B.length; i++)
        {
	    if (i != 0)
            {
		returnValue.append("\n");
	    }
	    for (int j = 0; j < B[i].length; j++)
            {
                if(B[i][j] < 1.0E-5)
                {
                    returnValue.append(zero).append(Model.SEPARATION_TOKEN);
                }
                else
                {
                    returnValue.append(B[i][j]).append(Model.SEPARATION_TOKEN);
                }
	    }
	}
        returnValue.deleteCharAt(returnValue.length() - 1);	

	return returnValue.toString();
    }

    /**
     * Funcion para escribir un modelo
     */
    public static void writeModel(Model lambda, String filename)
    {
        try {
                PrintWriter out = new PrintWriter(filename);
                
                out.println(lambda.toString());

                out.close();
        } catch (FileNotFoundException e) {}
    }
}
//--------------------------------------------------
//FIN
//--------------------------------------------------